import json
import logging
from datetime import timedelta

from django.core.paginator import Paginator
from django.utils import timezone

from django.db import transaction
from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from courses.models import Course, CourseExpire
from orders.models import Order, OrderDetail
from orders.serializers import OrderDetailSerializer, OrderDetailInfoSerializer
from utils.snowflake import generate_id

# Create your views here.
logger = logging.getLogger("django")


class OrderCreateAPIView(APIView):
    """
    创建订单
    """

    permission_classes = [IsAuthenticated]

    def post(self, request):
        """
        创建订单
        """
        # 获取前端传递的参数:
        course_list = request.data.get("courseList", [])
        pay_method = request.data.get("pay_method")
        use_coupon = request.data.get("use_coupon")
        use_coupon_id = request.data.get("use_coupon_id")
        total_price = request.data.get("total_price")
        real_price = request.data.get("real_price")

        logger.info(
            f"前端传递的参数[courseList]:{course_list},[pay_method]:{pay_method},[use_coupon]:{use_coupon},[total_price]:{total_price},[real_price]:{real_price}")

        if not course_list:
            return Response({"code": 0, "message": "课程列表不能为空"})

        user_id = request.user.id
        # h获取redis连接
        redis_conn = get_redis_connection('default')
        # 购物车的 hash KEY
        cart_key = f"code_env_space:cart:cartList:{user_id}"

        course_ids = [item['course_id'] for item in course_list]
        logger.info(f"前端传递的课程ID列表:{course_ids}")

        # 校验购物车中课程
        for course_id in course_ids:
            course_key = f"course_{course_id}"
            cart_item = redis_conn.hget(cart_key, course_key)
            if not cart_item:
                return Response({"code": 0, "message": "课程不存在"})

            cart_item = json.loads(cart_item.decode())
            logger.info(f"用户:[{user_id},购物车数据:[{cart_item}]]")
            if cart_item['is_selected'] == 0:
                return Response({"code": 0, "message": "购物车中存在未选中的课程"})

        # 校验课程的状态
        courses = Course.objects.filter(id__in=course_ids, status=1)
        logger.info(f"从数据库中获取的课程数据:[{courses}]")

        if len(courses) != len(course_list):
            return Response({"code": 0, "message": "存在未上架的课程"})

        # 校验价格
        calculate_total = 0

        for item in course_list:
            course_id = item['course_id']
            expire_time = item['expire_time']
            price = item['price']
            logger.info(f"从前端传递过来的数据,课程ID:[{course_id},有效时间:[{expire_time},价格:[{price}]]")

            if expire_time == 0:  # 永久有效
                course_price = Course.objects.get(id=course_id).price
                logger.info(f"从数据库中课程表获取的课程[{course_id}]价格:[{course_price}]")
            else:  # 有 有效期
                course_price = CourseExpire.objects.get(course_id=course_id, expire_time=expire_time).price
                logger.info(f"从数据库中课程有效期表获取的课程[{course_id}]价格:[{course_price}]")

            if float(price) != float(course_price):
                logger.info(f"前端传递的价格:[{price}]和数据库中获取的价格:[{course_price}]")
                return Response({"code": 0, "message": "价格有误"})

            calculate_total += course_price
            logger.info(f"计算后的总价格:[{calculate_total}]")

        if float(calculate_total) != float(total_price):
            logger.info(f"前端传递的订单总价格:[{total_price}]和计算后的总价格:[{calculate_total}]")
            return Response({"code": 0, "message": "订单总价格有误"})

        try:
            with transaction.atomic():
                # 创建订单
                order = Order.objects.create(
                    total_price=total_price,
                    real_price=real_price,
                    order_status=0,
                    pay_method=pay_method,
                    user=request.user,
                    order_number=str(generate_id()),
                    use_coupon=bool(use_coupon),
                    use_coupon_id=use_coupon_id if use_coupon else None,
                    order_desc=f"码境空间:{str(generate_id())}"
                )

                # 创建订单详情
                for item in course_list:
                    course_id = item['course_id']  # 课程ID
                    expire_days = item['expire_time']  # 有效期
                    expire_text = item['expire_text']
                    price = item['price']

                    logger.info(
                        f"创建订单详情====从前端传递过来的数据,课程ID:[{course_id},有效时间:[{expire_days},价格:[{price}]]")

                    expire_time = None
                    if expire_days != 0:
                        expire_time = timezone.now() + timedelta(days=expire_days)

                    OrderDetail.objects.create(
                        order=order,
                        course=Course.objects.get(id=course_id),
                        price=price,
                        expire_days=expire_days,
                        expire_text=expire_text,
                        expire_time=expire_time,
                        order_number=order.order_number
                    )

                # 删除购物车中已购买课程
                for course_id in course_ids:
                    course_key = f"course_{course_id}"
                    redis_conn.hdel(cart_key, course_key)

                return Response({"code": 1, "message": "创建订单成功",
                                 "data": {
                                     'order_number': order.order_number,
                                     'total_price': order.total_price,
                                     'real_price': order.real_price,
                                 }}
                                )
        except Exception as e:
            logger.error(e)
            return Response(
                {"code": 0, "message": f"创建订单失败:{str(e)}"})


class OrderDetailAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        """
        订单详情
        """

        order_number = request.query_params.get('order_number')
        if not order_number:
            return Response({"code": 0, "message": "订单号不能为空"})


        try:
            #query_set = OrderDetail.objects.filter(order_number=order_number)
            #ser = OrderDetailSerializer(query_set, many=True)
            order = Order.objects.get(order_number= order_number,user=request.user)
            logger.info(f"订单:[{order}]")
            ser = OrderDetailInfoSerializer(order)

            return Response({"code": 1, "message": "查询成功", "data": ser.data})

        except Exception as e:
            logger.error(e)
            return Response({"code": 0, "message": "查询失败"})




class OrderListAPIView(APIView):
    """
    订单列表接口
    """
    permission_classes = [IsAuthenticated]

    def get(self, request):
        page = int(request.query_params.get('page',1))
        page_size = int(request.query_params.get('page_size',10))

        try:
            #获取用户订单列表
            orders = Order.objects.filter(
                user = request.user
            ).prefetch_related(
                'order_details',  #预加载订单详情
                'order_details__course'  #预加载课程信息
            ).order_by('-created_time')

            #创建分页器
            pagination = Paginator(orders,page_size)

            #获取当前页的数据
            current_page= pagination.page(page)

            #current_page.object_list. 序列化数据
            ser = OrderDetailInfoSerializer(current_page.object_list,many=True)

            return Response({
                "code":1,
                "message":"查询成功",
                "data":{
                    "total":pagination.count,  #总记录数
                    "current_page":page, #当前页码
                    "page_size":page_size, #每页记录数
                    "total_pages":pagination.num_pages, #总页数
                    "results":ser.data #订单列表数据
                }
             })


        except Exception as e:
            logger.error(f"分页异常信息:{e}")
            return Response({
                "code": 0,
                "message": f"获取订单列表失败{str(e)}"
            })




